package delete.cn.merryyou.security.config;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;

import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.oauth2.common.exceptions.InvalidClientException;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.validation.BindException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;

import cn.merryyou.security.domain.Result;


/**
 * @author 作者 owen 
 * @version 创建时间：2017年11月12日 上午22:57:51 异常通用处理 服务于oauth 服务端于客户端
 * blog: https://blog.51cto.com/13005375 
 * code: https://gitee.com/owenwangwen/open-capacity-platform
 */
//@RestControllerAdvice
public class ExceptionHandlerAdvice {

    /**
     * API统一异常处理
     **/
    @ExceptionHandler(value = Exception.class)
    public Result<?> jsonApiErrorHandler(HttpServletRequest request, Exception e) {
    	return Result.error(HttpStatus.BAD_REQUEST.value(), e.getMessage());
    }
	/**
	 * IllegalArgumentException异常处理返回json 状态码:400
	 * 
	 * @param exception
	 * @return
	 */
	@ExceptionHandler({ IllegalArgumentException.class })
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	public Result<?> badRequestException(IllegalArgumentException e) {
		return Result.error(HttpStatus.BAD_REQUEST.value(), e.getMessage());
	}
	
	/**
	 * AccessDeniedException异常处理返回json 状态码:403
	 * 
	 * @param exception
	 * @return
	 */
	@ExceptionHandler({ AccessDeniedException.class })
	@ResponseStatus(HttpStatus.FORBIDDEN)
	public Result<?> badMethodExpressException(AccessDeniedException e) {
		return Result.error(HttpStatus.FORBIDDEN.value(), e.getMessage());
	}
	
	@ExceptionHandler(MissingServletRequestParameterException.class)
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	public Result<?> handleError(MissingServletRequestParameterException e) {
		return Result.error(HttpStatus.FORBIDDEN.value(), e.getMessage());
	}

	@ExceptionHandler(MethodArgumentTypeMismatchException.class)
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	public Result<?> handleError(MethodArgumentTypeMismatchException e) {
		return Result.error(HttpStatus.BAD_REQUEST.value(), e.getMessage());
	}

	@ExceptionHandler(MethodArgumentNotValidException.class)
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	public Result<?> handleError(MethodArgumentNotValidException e) {
		return Result.error(HttpStatus.BAD_REQUEST.value(), e.getMessage());
	}

	@ExceptionHandler(BindException.class)
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	public Result<?> handleError(BindException e) {
		return Result.error(HttpStatus.BAD_REQUEST.value(), e.getMessage());
	}

	@ExceptionHandler(ConstraintViolationException.class)
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	public Result<?> handleError(ConstraintViolationException e) {
		return Result.error(HttpStatus.BAD_REQUEST.value(), e.getMessage());
	}
	
	
	@ExceptionHandler(NoHandlerFoundException.class)
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
	public Result<?> handleError(NoHandlerFoundException e) {
		return Result.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
	}

	@ExceptionHandler(HttpMessageNotReadableException.class)
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
	public Result<?> handleError(HttpMessageNotReadableException e) {
		return Result.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
	}

	@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
	@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
	public Result<?> handleError(HttpRequestMethodNotSupportedException e) {
		return Result.error(HttpStatus.METHOD_NOT_ALLOWED.value(), e.getMessage());
	}
	
    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public Result<?> handleError(HttpMediaTypeNotSupportedException e) {
		return Result.error(HttpStatus.UNSUPPORTED_MEDIA_TYPE.value(), e.getMessage());
    }

	@ExceptionHandler({ DataAccessException.class })
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
	public Result<?> dataAccessException(DataAccessException e) {
		return Result.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
	}


	//ClientAuthenticationException
	@ExceptionHandler({ OAuth2Exception.class })
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	public Result<?> handleError(InvalidGrantException e) {
		return Result.error(e.getHttpErrorCode(), e.getMessage());
	}	
	
	@ExceptionHandler({ InvalidClientException.class })
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	public Result<?> handleError(InvalidClientException e) {
		return Result.error(e.getHttpErrorCode(), e.getMessage());
	}	

	@ExceptionHandler(Throwable.class)
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
	public Result<?> handleError(Throwable e) {
		return Result.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
	}
}
